package kryptologieBlatt1;
import java.util.Vector;


public class KasiskiTest {
	
	private String chiffre;
	private int chiffreLength;
	private int sequenceLength;
	private Vector<Integer> offsets;
	private String primeFactorsOfOffsets;
	private Vector<String> sequences;
	private Vector<Vector<Integer>> allPrimes;
	private Vector<Integer> usedPrimes;
	private Vector<Integer> primeFreqs;
	private int keyLength;
	
	
	public KasiskiTest(String chiffreText) {
		initVariables(chiffreText);
	}
	
	private void initVariables(String chiffreText){
		this.chiffre = chiffreText;
		this.chiffreLength = chiffre.length();
		this.sequenceLength = 3;
		this.offsets = new Vector<Integer>(0);
		this.sequences = new Vector<String>(0);
		this.allPrimes = new Vector<Vector<Integer>>(0);
		this.usedPrimes = new Vector<Integer>(0);
		this.primeFreqs = new Vector<Integer>(0);
		this.keyLength = 0;
	}
	
	public int getKeyLength() {
		countSequenceOffsets();
		calcPrimeFactorsFromOffsets();
		getPrimeFrequencies();
		getMaxFreqPrime();
		return keyLength;
	}
	
	private void getMaxFreqPrime(){
		int max = 0;
		int index = 0;
		int acc = 0;
		int length = primeFreqs.size();
		for (int i = 0; i < length; i++) {
			acc = primeFreqs.get(i);
			if(acc > max){
				max = acc;
				index = i;
			}
		}
		keyLength = usedPrimes.get(index);
	}
	
	private void getPrimeFrequencies() {
		int length = allPrimes.size();
		String statistic = "";
		int count = 0;
		int prime = 0;
		for (int j = 0; j < usedPrimes.size(); j++) {
			prime = usedPrimes.get(j);
			for (int i = 0; i < length; i++) {
				Vector<Integer> vec = allPrimes.get(i);
				if(vec.contains(prime))
					count++;
			}
			primeFreqs.add(count);
			statistic += "Primzahl " + prime + " hat " + count + " Vorkommnisse! \n";
			count = 0;
		}
//		System.out.println(statistic);
	}

	private void calcPrimeFactorsFromOffsets() {
		String acc = "";
		int val = 0;
		int length = offsets.size();
		String temp = "";
		Vector<Integer> primesPerSequence = new Vector<Integer>(0);
		String[] tmp;
		for (int i = 0; i < length; i++) {
			val = offsets.get(i);
			temp = calcPrimeFactors(val);
			tmp = temp.split(", ");
			for (int j = 0; j < tmp.length; j++) {
				primesPerSequence.add(Integer.parseInt(tmp[j]));
			}
			allPrimes.add(primesPerSequence);
			primesPerSequence = new Vector<Integer>(0);
			acc += sequences.get(i) + ": " + temp + "\n";
		}
		primeFactorsOfOffsets = acc;
	}
	
	private String calcPrimeFactors(int val){
		int upperLimit = (int) Math.ceil(Math.sqrt(val));
		int count = val;
		String acc = "";
		for (int i = 2; i < upperLimit; i++) {
			while (count % i == 0){
				acc += i + ", ";
				if(!usedPrimes.contains(i)){
					usedPrimes.add(i);
				}
				count = count / i;
			}
		}
		if(count > 1) acc += count + "";
		else acc = acc.substring(0, acc.length() - 2);
		return acc;
	}

	private void countSequenceOffsets(){
		int length = chiffreLength - sequenceLength + 1;
		String sequence = "";
		String chiffreClone = chiffre;
		int index = 0;
		for (int i = 0; i < length; i++) {
			sequence = chiffreClone.substring(0, 0 + sequenceLength);
			chiffreClone = chiffreClone.substring(1, chiffreClone.length());
			if(chiffreClone.contains(sequence)){
				index = chiffreClone.indexOf(sequence) + 1;
				offsets.add(index);
				sequences.add(sequence);
			}
		}
	}
	
}
